package com.niiwoo.civet.trade.service.dubbo.myloan;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.niiwoo.activity.event.enums.FlowProjectTypeEventEnum;
import com.niiwoo.activity.stage.dto.request.prize.ActivityPrizeResetStatusReqDTO;
import com.niiwoo.activity.stage.service.prize.ActivityPrizeDubboService;
import com.niiwoo.asset.cardniu.dto.mq.CardNiuExternalMQConstants;
import com.niiwoo.asset.cardniu.dto.request.LoanStatusDTO;
import com.niiwoo.asset.constant.MqConstants;
import com.niiwoo.asset.dto.mq.R360OrderStatusChangedDTO;
import com.niiwoo.asset.enums.r360.R360OrderProjectSubStatusEnum;
import com.niiwoo.asset.enums.r360.R360OrderStatusEnum;
import com.niiwoo.civet.trade.constant.MqConstant;
import com.niiwoo.civet.trade.dao.entity.Project;
import com.niiwoo.civet.trade.dao.mapper.ProjectFlowExecuteMapperExt;
import com.niiwoo.civet.trade.dto.common.ProjectBorrowerPlanDTO;
import com.niiwoo.civet.trade.dto.common.ProjectBorrowerSummaryDTO;
import com.niiwoo.civet.trade.dto.request.CancelProjectMQDTO;
import com.niiwoo.civet.trade.dto.request.myloan.*;
import com.niiwoo.civet.trade.dto.response.myloan.*;
import com.niiwoo.civet.trade.dto.response.newRefund.OrgImmediateRepaymentResponseDTO;
import com.niiwoo.civet.trade.enums.ProjectFromSourceEnum;
import com.niiwoo.civet.trade.enums.ProjectStatusEnum;
import com.niiwoo.civet.trade.enums.ProjectSubStatusEnum;
import com.niiwoo.civet.trade.service.local.activity.ActivityEventService;
import com.niiwoo.civet.trade.service.local.flowexecute.ProjectFlowExecuteService;
import com.niiwoo.civet.trade.service.local.myloan.MyLoanLocalService;
import com.niiwoo.civet.trade.service.local.project.ProjectLocalService;
import com.niiwoo.civet.trade.service.myloan.MyLoanDubboService;
import com.niiwoo.civet.user.dto.request.UserLetterRequestDTO;
import com.niiwoo.civet.user.enums.MessageTemplateKeyEnum;
import com.niiwoo.civet.user.enums.UserLetterTypeEnum;
import com.niiwoo.civet.user.service.UserLetterDubboService;
import com.niiwoo.tripod.provider.dto.response.PageResponseDTO;
import com.niiwoo.tripod.provider.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Slf4j
@Service(version = "1.0.0")
public class MyLoanDubboServiceImpl implements MyLoanDubboService {
	@Autowired
	private MyLoanLocalService myLoanLocalService;
	@Autowired
	private ProjectLocalService projectLocalService;
	@Reference(version = "1.0.0")
	private ActivityPrizeDubboService activityPrizeDubboService;
	@Autowired
	private RabbitTemplate rabbitTemplate;
	@Reference(version = "1.0.0")
	private UserLetterDubboService userLetterDubboService;
	@Autowired
	private ActivityEventService activityEventService;
	@Autowired
    private ProjectFlowExecuteService projectFlowExecuteService;

	@Autowired
    private ProjectFlowExecuteMapperExt projectFlowExecuteMapperExt;


	/**
	 * 借款首页数据查询
	 *
	 * @param userId
	 * @return
	 */
	@Override
	public LoanIndexQueryResponseDTO loanIndexQuery(String userId) {
		Assert.notNull(userId, "用户ID不能为空");
		return myLoanLocalService.loanIndexQuery(userId);
	}


    /**
     * 还款计划-按日查看
     *
     * @param dto
     * @return
     */
    @Override
    public PageResponseDTO<LoanPlanDateResponseDTO> loanPlanDateQuery(MyloanRequestDTO dto) {
        Assert.notNull(dto, "请求参数缺失");
        Assert.notNull(dto.getUserId(), "用户ID不能为空");
        return myLoanLocalService.loanPlanDateQuery(dto);
    }

    @Override
    public PageResponseDTO<LoanPlanMonthResponseDTO> loanPlanMonthQuery(MyloanRequestDTO dto) {
        Assert.notNull(dto, "请求参数缺失");
        Assert.notNull(dto.getUserId(), "用户ID不能为空");
        return myLoanLocalService.loanPlanMonthQuery(dto);
    }

    @Override
    public Integer queryNotSettlementLoanCount(String userId){
    	Assert.notNull(userId, "请求参数缺失");
    	return myLoanLocalService.queryNotSettlementLoanCount(userId);
    }

    @Override
    public PageResponseDTO<LoanGoingResponseDTO> myloanGoingQuery(MyloanRequestDTO dto) {
        Assert.notNull(dto, "请求参数缺失");
        Assert.notNull(dto.getUserId(), "用户ID不能为空");
        return myLoanLocalService.myloanGoingQuery(dto);
    }

    @Override
    public PageResponseDTO<LoanEndResponseDTO> myloanEndedQuery(MyloanRequestDTO dto){
        Assert.notNull(dto, "请求参数缺失");
        Assert.notNull(dto.getUserId(), "用户ID不能为空");
        return myLoanLocalService.myloanEndedQuery(dto);
    }

    @Override
    public PageResponseDTO<BackToArticleByDayResponseDTO> backToArticleDay(MyloanRequestDTO dto) {
        org.springframework.util.Assert.notNull(dto, "数据不可空");
        org.springframework.util.Assert.notNull(dto.getUserId(), "用户ID不可空");
        return myLoanLocalService.backToArticleDay(dto);
    }

    public PageResponseDTO<InvestorPlanDTO> backToArticleDayByDay(MyloanRequestDTO dto, Date receivedDate){
    	return myLoanLocalService.backToArticleDayByDay(dto, receivedDate);
    }


	@Override
	public ImmediateRepaymentResponseDTO queryImmediateRepayment(MyProjectRequestDTO dto) {
		org.springframework.util.Assert.notNull(dto, "数据不可空");
		org.springframework.util.Assert.notNull(dto.getUserId(), "用户ID不可空");
		return myLoanLocalService.queryImmediateRepayment(dto);
	}

	@Override
	public OrgImmediateRepaymentResponseDTO queryOrgImmediateRepayment(String userId, String orgId) {
		org.springframework.util.Assert.notNull(userId, "数据不可空");
		return myLoanLocalService.queryOrgImmediateRepayment(userId, orgId);
	}

	@Override
	public ContractResponseDTO contractQuery(MyProjectRequestDTO dto) {
		org.springframework.util.Assert.notNull(dto, "数据不可空");
		org.springframework.util.Assert.notNull(dto.getUserId(), "用户ID不可空");
		org.springframework.util.Assert.notNull(dto.getProjectId(), "标的ID不可空");
		return myLoanLocalService.queryContractByProjectId(dto);
	}
	@Override
	public PageResponseDTO<BackToArticleByMonResponseDTO> listBackToArticleByMonth(MyloanRequestDTO dto) {
		org.springframework.util.Assert.notNull(dto, "数据不可空");
		org.springframework.util.Assert.notNull(dto.getUserId(), "用户ID不可空");
		return myLoanLocalService.listBackToArticleByMonth(dto);
	}



	@Override
	public QueryProjectBorrowDetailReponseDTO queryProjectBorrowDetail(Long projectId, String userId) {
		return myLoanLocalService.queryProjectBorrowDetail(projectId, userId);
	}

	@Override
	public QueryProjectBorrowDetailAPPReponseDTO queryProjectBorrowDetailAPP(Long projectId, String userId) {
		return myLoanLocalService.queryProjectBorrowDetailAPP(projectId, userId);
	}

    @Override
    public QueryFullAmountRepaymentReponseDTO queryFullAmountRepayment(Long projectId, String userId) {
        return myLoanLocalService.queryFullRepayAmount(projectId, userId);
    }


	@Override
	public QueryRepaymentPlanResponseDTO queryRepaymentPlan(Long projectId, String userId) {
		return myLoanLocalService.queryRepaymentPlan(projectId, userId);
	}
	@Override
	public QueryProjectDynamicReponseDTO queryProjectDynamic(Long projectId, String userId) {
		return myLoanLocalService.queryProjectDynamic(projectId, userId);
	}

	@Override
	public ProjectDetailResponseDTO queryProjectDetailByProjectId(Long projectId) {

		return myLoanLocalService.queryProjectDetailByProjectId(projectId);
	}

	@Override
	public Integer publishProject(LoanProjectRequestDTO dto){
		Assert.notNull(dto,"参数对象不可空");
		Assert.notNull(dto.getProjectId(),"标的号不可空");
		Assert.notNull(dto.getUserId(),"用户ID不可空");
		return myLoanLocalService.publishProject(dto);
	}

	@Override
	public void cancelProject(LoanProjectRequestDTO dto){
		Assert.notNull(dto,"参数对象不可空");
		String userId = dto.getUserId();
		Long projectId = dto.getProjectId();
		Assert.notNull(projectId,"标的号不可空");
		Assert.notNull(userId,"用户ID不可空");

		Project project = projectLocalService.selectByUserIdAndProjectId(userId, projectId);
		Assert.notNull(project,"不存在此项目");
		//this.cancelProjectCheck(project);

		myLoanLocalService.cancelProject(dto);
		//回退红包
		this.cancelProjectResetPrize(userId,project);

		// 如果存在流程则删除流程信息，只有小易贷、社保贷和信用卡贷才需要
    	/*ProjectFlowExecute projectFlowExecute = projectFlowExecuteMapperExt.selectLastByProjectIdForUpdate(projectId);
		if (projectFlowExecute != null) {
			projectFlowExecuteService.failEndProjectFlowExecute(projectFlowExecute.getFlowExecuteId(), LoanNodeTypeEnum.enumof(projectFlowExecute.getEndNodeId()), "用户取消借款");
		}*/

		// 通知资产端
		notifyAssetForR360(project);

		LoanStatusDTO loanStatusDTO = new LoanStatusDTO();
		loanStatusDTO.setProjectId(projectId);
		loanStatusDTO.setStatus(ProjectSubStatusEnum.MISCARRY_CANCER_BORROWER.getParentStatusEnum().getStatus());
		loanStatusDTO.setSubStatus(ProjectSubStatusEnum.MISCARRY_CANCER_BORROWER.getSubStatus());
		loanStatusDTO.setType(project.getType());
		log.info("卡牛-取消借款:{}", JSON.toJSON(loanStatusDTO));
		rabbitTemplate.convertAndSend(CardNiuExternalMQConstants.Exchange.LOAN_STATUS_EXCHANGE,
				CardNiuExternalMQConstants.getRoutingKey(CardNiuExternalMQConstants.Exchange.LOAN_STATUS_EXCHANGE, CardNiuExternalMQConstants.Queue.LOAN_STATUS_QUEUE), loanStatusDTO);

		//取消标的消息推送
		/*this.cancelProjectMessagePush(project.getTitle(),userId,projectId);*/

		//发送取消标的MQ消息
		/*this.cancelProjectSendMQ(userId,projectId);*/

		//用户流标事件通知
		activityEventService.sendMsgForFlowProject(projectId, FlowProjectTypeEventEnum.USER_FLOW);
	}

	private void notifyAssetForR360(Project project){

		if (project == null) {
			return;
		}

		if (project.getFromSource() != null && project.getFromSource().byteValue() == ProjectFromSourceEnum.R360.getType()) {
			try {
				R360OrderStatusChangedDTO r360OrderStatusChangedDTO = new R360OrderStatusChangedDTO();
				r360OrderStatusChangedDTO.setProjectId(project.getProjectId());
				r360OrderStatusChangedDTO.setR360OrderStatusEnumCode(R360OrderStatusEnum.LOAN_CANCEL.getCode());
				r360OrderStatusChangedDTO.setR360OrderProjectSubStatusEnum(R360OrderProjectSubStatusEnum.MISCARRY_CANCER_BORROWER);
				r360OrderStatusChangedDTO.setUpdateDate(new Date());
				rabbitTemplate.convertAndSend(MqConstants.Exchange.ASSET_EXCHANGE, MqConstants.getRoutingKey(MqConstants.Exchange.ASSET_EXCHANGE, MqConstants.Queue.ORDER_STATUS_NOFIFY_FOR_COMMON),
						r360OrderStatusChangedDTO);
				log.info("融360标在你我APP取消借款通知资产端成功，projectId:{}", project.getProjectId());
			} catch (Exception e) {
				log.error("融360标在你我APP取消借款通知资产端失败，projectId:{}", project.getProjectId(), e);
			}
		}

	}

	//取消标的消息推送
	private void cancelProjectMessagePush(String projectTitle,String userId,Long projectId){
		try {
			UserLetterRequestDTO userLetterRequestDTO = new UserLetterRequestDTO();
			userLetterRequestDTO.setLetterTemplateEnum(MessageTemplateKeyEnum.LetterTemplateKeyEnum.USER_CANCEL_LOAN_PROJECT);
			userLetterRequestDTO.setLetterTemplateParamList(Arrays.asList(
					projectId,
					projectTitle
			));
			userLetterRequestDTO.setToUserId(userId);
			userLetterRequestDTO.setProjectId(projectId);
			userLetterRequestDTO.setUserLetterTypeEnum(UserLetterTypeEnum.ONLY_LETTER);
			userLetterDubboService.pushLetter(userLetterRequestDTO);
		}catch(Exception e){
			log.error("用户取消借款标的,标的ID={},发送通知时发生异常,错误信息={}", projectId,e);
		}
	}

	private void cancelProjectCheck(Project project){
		if(ProjectStatusEnum.CHECKING.getStatus()!=project.getStatus().byteValue()){
			throw new BizException("TRD30006");
		}
	}

	//回退红包
	private void cancelProjectResetPrize(String userId,Project project){
		Long prizeId = project.getPrizeId();
		//“101审核中-借款退回”状态不需要回退红包，回退红包在标的审核回退的时候已经回退了
		if(prizeId==null ){
			return;
		}
		ActivityPrizeResetStatusReqDTO activityPrizeResetStatusReqDTO = new ActivityPrizeResetStatusReqDTO();
		activityPrizeResetStatusReqDTO.setUserId(userId);
		activityPrizeResetStatusReqDTO.setPrizeId(prizeId);
		activityPrizeDubboService.resetPrizeToReturned(activityPrizeResetStatusReqDTO);
	}

	private void cancelProjectSendMQ(String userId,Long projectId){
		try {
			JSONObject jsonObject = new JSONObject();
			jsonObject.put("projectId", projectId);
			jsonObject.put("borrowerUserId", userId);
			String json = JSON.toJSONString(jsonObject);
			log.info("流标###发送标的快照mq###data={}", json);
			rabbitTemplate.convertAndSend(MqConstant.CREATE_PROJECT_SNAPSHOT_EXCHANGE, MqConstant.CREATE_PROJECT_SNAPSHOT_ROUTE, json);
		} catch (AmqpException e) {
			log.info("流标###发送标的快照mq.projectId={} error",projectId);
		}
		try {
			log.info("cancelProjectSendMQ projectId={}",projectId);
			CancelProjectMQDTO cancelProjectMQDTO = new CancelProjectMQDTO();
			cancelProjectMQDTO.setProjectId(projectId);
			String jsonString = JSON.toJSONString(cancelProjectMQDTO);
			log.info("cancelProjectSendMQ.projectId={},cancelProjectMQDTO={}",projectId,jsonString);
			rabbitTemplate.convertAndSend(MqConstant.AUDIT_WORK_TASK_EXCHANGE, MqConstant.AUDIT_WORK_TASK_CANCEL_ROUTE, jsonString);
			log.info("cancelProjectSendMQ.projectId={} end",projectId);
		} catch (Exception e) {
			log.info("cancelProjectSendMQ.projectId={} error",projectId);
		}
	}

	@Override
	public UserProjectStatisticResponseDTO queryProjectInfoDetail(MyProjectRequestDTO requestDTO){
		Assert.notNull(requestDTO,"对象不可空");
		Assert.notNull(requestDTO.getProjectId(),"标的对象不可空");
		return myLoanLocalService.queryProjectInfoDetail(requestDTO);
	}

	@Override
	public ProjectInvestorPlanResponseDTO queryProjectInvestorPlan(String userId, Long projectId) {

		return myLoanLocalService.queryProjectInvestorPlan(userId, projectId);
	}

	@Override
	public QueryRepaymentPlanResponseDTO queryRepaymentPlanDetail(Long projectId,String userId){

		return myLoanLocalService.queryRepaymentPlanDetail(projectId, userId);
	}

	/**
	 * 查询我的还款计划(只查询今天该还款的还款计划)
	 * @return
	 */
	@Override
	public List<ProjectBorrowerPlanDTO> queryMyLoanPlanByToday(String userId) {
		Assert.notNull(userId,"用户ID不可空");
		return myLoanLocalService.queryMyLoanPlanByToday(userId);
	}


	/**
	 * 查询我的逾期还款标的
	 * @return
	 */
	@Override
	public List<ProjectBorrowerSummaryDTO> queryMyLoanOverdue(String userId) {
		Assert.notNull(userId,"用户ID不可空");
		return myLoanLocalService.queryMyLoanOverdue(userId);
	}

	@Override
	public Integer isExistOverdueAndRepaymentProject(String userId){
		return myLoanLocalService.isExistOverdueAndRepaymentProject(userId);
	}

	public LoanVoucherAuditInfoQueryResponseDTO loanVoucherAuditInfoQuery(LoanVoucherAuditInfoQueryRequestDTO requestDTO){
		return myLoanLocalService.loanVoucherAuditInfoQuery(requestDTO);
	}

	public void loanVoucherSubmit(LoanVoucherSubmitRequestDTO requestDTO){
		myLoanLocalService.loanVoucherInfoSave(requestDTO);
	}

	public BigDecimal queryUserToPayCapital(String userId){
		return myLoanLocalService.queryUserToPayCapital(userId);
	}
}
